using System;
using System.Collections.Generic;
using System.Text;
using ACS.Compiler.Tables;
using ACS.Compiler.Tables.Modes;
using ACS.Compiler.Tree.Interfaces;
using ACS.Compiler.Util;

namespace ACS.Compiler.Tree.Impl
{
    public abstract class Expression : TreeBase, IExpression
    {

        public abstract Expressions ExpressionType
        {
            get;
        }

        protected Mode _mode;

        public virtual Mode Mode
        {
            get { return _mode; }
        }

        public override TreeTags Tag
        {
            get
            {
                switch (ExpressionType)
                {
                    case Expressions.Select:
                        return TreeTags.Select;
                    case Expressions.Slice:
                        return TreeTags.Slice;
                    case Expressions.Ident:
                        return TreeTags.Ident;
                    case Expressions.StringConst:
                        return TreeTags.StringConst;
                    case Expressions.IntConst:
                        return TreeTags.IntConst;
                    case Expressions.BoolConst:
                        return TreeTags.BoolConst;
                    case Expressions.Plus:
                        return TreeTags.Plus;
                    case Expressions.Star:
                        return TreeTags.Star;
                    case Expressions.Arrow:
                        return TreeTags.Arrow;
                    case Expressions.Call:
                        return TreeTags.Call;
                    case Expressions.Eqq:
                        return TreeTags.Eqq;
                }
                throw new Exception("Wrong expression type");
            }
        }

        public enum Expressions
        {
            Select, 
            Slice, 
            Ident, 
            StringConst,
            IntConst,
            BoolConst,
            Plus,
            Star,
            Arrow,
            Call,
            Eqq
        }

        public Mode ModeResolveExpression(string ns, DataTable localData, Mode parentMode)
        {
            Mode mode;
            switch (ExpressionType)
            {
                case Expressions.Select:
                case Expressions.Slice:
                case Expressions.Ident:
                    mode = ((IFinalIdent)this).ResolveIdent(ns, localData, parentMode);
                    return mode;
                default:
                    Resolve(ns, localData);
                    mode = Mode;
                    break;
            }
            if (mode == null)
            {
                Logger.Instance.TraceError("Resolve error.", this);
            }
            return mode;
        }

        public abstract void Resolve(string ns, DataTable localData);

        public abstract string ToDeclareString();
    }
}
